home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / cmp.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  3KB  |  133 lines

  1. /* cmp - compare two files    Authors: Paul Polderman & Michiel Huisjes */
  2.  
  3. /* 90-04-10 Schlenker
  4.  *    Fixed incorrect handling of flags.
  5.  *    Reduced buffer size to accommodate 7K pipes (Minix restriction).
  6.  *    Better trapping of file reading errors.
  7.  *    Considerable speedup when using -s flag.
  8.  *    Buffering strategy remains seriously error prone; should be fixed.
  9.  */
  10.  
  11. #include <sys/types.h>
  12. #include <fcntl.h>
  13. #include <unistd.h>
  14. #include <stdio.h>
  15.  
  16. #define BLOCK_SIZE 6144
  17.  
  18. char *file_1, *file_2;
  19. char buf1[BLOCK_SIZE];
  20. char buf2[BLOCK_SIZE];
  21. char lflag, sflag;
  22.  
  23. main(argc, argv)
  24. int argc;
  25. char *argv[];
  26. {
  27.   int fd1, fd2, i, exit_status;
  28.  
  29.   if (argc < 3 || argc > 4) usage();
  30.   lflag = 0;
  31.   sflag = 0;
  32.  
  33.   i = 1;
  34.   if (strcmp(argv[i], "-l") == 0) {
  35.     lflag++;
  36.     i++;
  37.   } else
  38.   if (strcmp(argv[i], "-s") == 0) {
  39.     sflag++;
  40.     i++;
  41.   }
  42.  
  43.   if (strcmp(argv[i], "-") == 0) {
  44.     fd1 = 0;
  45.     file_1 = "<stdin>";
  46.   } else {
  47.     if ((fd1 = open(argv[i], O_RDONLY)) < 0)
  48.         cantopen(argv[i]);
  49.     file_1 = argv[i];
  50.   }
  51.   i++;
  52.  
  53.   if (i == argc || (fd2 = open(argv[i], O_RDONLY)) < 0)
  54.     cantopen(argv[i]);
  55.   file_2 = argv[i];
  56.  
  57.   exit_status = sflag ? fastcmp(fd1, fd2) : cmp(fd1, fd2);
  58.  
  59.   close(fd1);
  60.   close(fd2);
  61.  
  62.   exit(exit_status);
  63. }
  64.  
  65. cmp(fd1, fd2)
  66. int fd1, fd2;
  67. {
  68.   register unsigned long char_cnt, line_cnt;
  69.   register int i;
  70.   int n1, n2, n, exit_status;
  71.  
  72.   char_cnt = 1L;
  73.   line_cnt = 1L;
  74.   exit_status = 0;
  75.   do {
  76.     n1 = read(fd1, buf1, BLOCK_SIZE);
  77.     n2 = read(fd2, buf2, BLOCK_SIZE);
  78.     n = (n1 < n2) ? n1 : n2;
  79.     if (n < 0) {
  80.         printf("cmp: Error on %s\n", (n1 < 0) ? file_1 : file_2);
  81.         return(1);
  82.     }
  83.     for (i = 0; i < n; i++) {    /* Check buffers for equality */
  84.         if (buf1[i] != buf2[i]) {
  85.             if (!lflag) {
  86.                 printf("%s %s differ: char %ld, line %ld\n",
  87.                 file_1, file_2, char_cnt, line_cnt);
  88.                 return(1);
  89.             }
  90.             printf("%10lu %03o %03o\n",
  91.                    char_cnt, buf1[i] & 0377, buf2[i] & 0377);
  92.             exit_status = 1;
  93.         }
  94.         if (buf1[i] == '\n') line_cnt++;
  95.         char_cnt++;
  96.     }
  97.     if (n1 != n2) {        /* EOF on one of the input files. */
  98.         printf("cmp: EOF on %s\n", (n1 < n2) ? file_1 : file_2);
  99.         return(1);
  100.     }
  101.   } while (n > 0);        /* While not EOF on any file */
  102.   return(exit_status);
  103. }
  104.  
  105. fastcmp(fd1, fd2)
  106. int fd1, fd2;
  107. {
  108.   int n1, n2;
  109.  
  110.   while (1) {
  111.     n1 = read(fd1, buf1, BLOCK_SIZE);
  112.     n2 = read(fd2, buf2, BLOCK_SIZE);
  113.     if (n1 != n2) return(1);    /* Bug! - depends on buffering */
  114.     if (n1 == 0) return(0);
  115.     if (n1 < 0) return(1);
  116.     if (memcmp((void *) buf1, (void *) buf2, (size_t) n1) != 0)
  117.         return(1);
  118.   }
  119. }
  120.  
  121. usage()
  122. {
  123.   fprintf(stderr, "Usage: cmp [-l | -s] file1 file2\n");
  124.   exit(2);
  125. }
  126.  
  127. cantopen(s)
  128. char *s;
  129. {
  130.   fprintf(stderr, "cmp: cannot open %s\n", s);
  131.   exit(1);
  132. }
  133.